package bp.wf.dts;


import bp.da.*;
import bp.en.*;
import bp.sys.GEEntity;
import bp.sys.GloVar;
import bp.sys.MapData;
import bp.tools.StringHelper;
import bp.web.WebUser;
import bp.wf.*;
import bp.wf.template.Task;

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.time.*;

/** 
 Method 的摘要说明
*/
public class AutoRunStratFlows extends Method
{
	/** 
	 不带有参数的方法
	*/
	public AutoRunStratFlows()
	{
		this.Title = "自动启动流程";
		this.Help = "在流程属性上配置的信息,自动发起流程,按照时间规则....";
		this.GroupName = "流程自动执行定时任务";

	}
	/** 
	 设置执行变量
	 
	 @return 
	*/
	@Override
	public void Init()
	{
	}
	/** 
	 当前的操纵员是否可以执行这个方法
	*/
	@Override
	public boolean getIsCanDo()
	{
		return true;
	}

    // 灵活解析时间为今天的完整时间点，支持：
    // HH:mm、H:mm、HH:mm:ss、H:mm:ss、MM-dd HH:mm、M-d H:m、MM-dd HH:mm:ss、M-d H:m:s、
    // yyyy-MM-dd HH:mm、yyyy-M-d H:m、yyyy-MM-dd HH:mm:ss、yyyy-M-d H:m:s
    private LocalDateTime parseFlexibleDateTime(String timeStr) {
        String s = timeStr.trim();

        // 1) 带年份
        String[] yearPatterns = new String[]{
                "yyyy-MM-dd HH:mm:ss",
                "yyyy-M-d H:m:s",
                "yyyy-MM-dd HH:mm",
                "yyyy-M-d H:m"
        };
        for (String p : yearPatterns) {
            try {
                DateTimeFormatter f = DateTimeFormatter.ofPattern(p);
                return LocalDateTime.parse(s, f);
            } catch (DateTimeParseException ignored) { }
        }

        // 2) 月-日 + 时间（补全年份）
        String[] mdPatterns = new String[]{
                "MM-dd HH:mm:ss",
                "M-d H:m:s",
                "MM-dd HH:mm",
                "M-d H:m"
        };
        for (String p : mdPatterns) {
            try {
                String withYear = LocalDate.now().getYear() + "-" + s;
                DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-" + p);
                return LocalDateTime.parse(withYear, f);
            } catch (DateTimeParseException ignored) { }
        }

        // 3) 仅时间（补齐今天日期）
        String[] timePatterns = new String[]{
                "HH:mm:ss",
                "H:m:s",
                "HH:mm",
                "H:m"
        };
        for (String p : timePatterns) {
            try {
                DateTimeFormatter f = DateTimeFormatter.ofPattern(p);
                LocalTime t = LocalTime.parse(s, f);
                return LocalDateTime.of(LocalDate.now(), t);
            } catch (DateTimeParseException ignored) { }
        }

        throw new DateTimeParseException("无法解析时间格式: " + timeStr, timeStr, 0);
    }


	/** 
	 执行
	 
	 @return 返回执行结果
	*/
	@Override
	public Object Do() throws Exception {
		Flows fls = new Flows();
		fls.RetrieveAll();

		String msg = "开始执行自动发起流程 :" + DataType.getCurrentDateTimess();

        LocalDateTime dt = LocalDateTime.now();


			///#region 自动启动流程
		for (Flow fl : fls.ToJavaList())
		{
			if (fl.getHisFlowRunWay() == FlowRunWay.HandWork)
			{
				continue;
			}

			msg += "<br>扫描：" + fl.getName();


				///#region 高级设置模式，是否达到启动的时间点？
            // 高级设置模式，是否达到启动的时间点？
            // 包含：指定人员按时启动、指定人员按时启动（高级）、让管理员发送给指定人员
            if (fl.getHisFlowRunWay() == FlowRunWay.SpecEmpAdv
                    || fl.getHisFlowRunWay() == FlowRunWay.SpecEmp
                    || fl.getHisFlowRunWay() == FlowRunWay.LetAdminSendSpecEmp)
            {
                String currTime = DataType.getCurrentDateTime(); //2022-09-01 09:10
                String[] strs = null;

                if (fl.getHisFlowRunWay() == FlowRunWay.SpecEmp)
                {
                    strs = fl.getRunObj().split("[@]", -1);
                }

                if (fl.getHisFlowRunWay() == FlowRunWay.SpecEmpAdv
                        || fl.getHisFlowRunWay() == FlowRunWay.LetAdminSendSpecEmp)
                {
                    String guide2 = fl.getStartGuidePara2();
                    if (DataType.IsNullOrEmpty(guide2)) {
                        // 未配置时间点则跳过
                        continue;
                    }
                    strs = guide2.split("[@]", -1); //@11:15@12:15
                }

				boolean isHave = false; //是否可以执行.
				for (String s : strs)
				{
					if (DataType.IsNullOrEmpty(s) == true)
					{
						continue;
					}
					// 去除首尾空格
					String str = s.trim();

					//如果有周.
					if (str.contains("Week.") == true)
					{
						if (str.contains("Week.1") == true && dt.getDayOfWeek() != DayOfWeek.MONDAY)
						{
							continue;
						}
						if (str.contains("Week.2") == true && dt.getDayOfWeek() != DayOfWeek.TUESDAY)
						{
							continue;
						}
						if (str.contains("Week.3") == true && dt.getDayOfWeek() != DayOfWeek.WEDNESDAY)
						{
							continue;
						}
						if (str.contains("Week.4") == true && dt.getDayOfWeek() != DayOfWeek.THURSDAY)
						{
							continue;
						}
						if (str.contains("Week.5") == true && dt.getDayOfWeek() != DayOfWeek.FRIDAY)
						{
							continue;
						}
						if (str.contains("Week.6") == true && dt.getDayOfWeek() != DayOfWeek.SATURDAY)
						{
							continue;
						}
						if (str.contains("Week.7") == true && dt.getDayOfWeek() != DayOfWeek.SUNDAY)
						{
							continue;
						}

						str = str.replace("Week.1", "");
						str = str.replace("Week.2", "");
						str = str.replace("Week.3", "");
						str = str.replace("Week.4", "");
						str = str.replace("Week.5", "");
						str = str.replace("Week.6", "");
						str = str.replace("Week.7", "");
						str = str.trim();
					}

					//是否每月的最后一天？
					if (str.contains("LastDayOfMonth") == true)
					{
						//获得当前月份有多少天.
						int days = LocalDate.now().lengthOfMonth();
						if (dt.getDayOfMonth() != days)
						{
							continue;
						}
						str = str.replace("LastDayOfMonth", "").trim();
					}

				//如果自动发起流程过多，会延迟判断时间点，要补偿自动发起
				if (!str.contains(":"))
				{
					continue;
				}

				// 逻辑修正， 不包含: 不执行，不用再判断:
				//是不是到时间了？
				//if (str.contains(":"))
				//{
					int i = str.length();
					String currTime01 = currTime.substring(currTime.length() - i);
					
					// 使用灵活解析，统一支持多种格式
					LocalDateTime dt1;
					LocalDateTime dt2;
					try {
						dt1 = parseFlexibleDateTime(str);
						dt2 = parseFlexibleDateTime(currTime01);
					} catch (Exception parseEx) {
						Log.DebugWriteError("解析时间点失败: " + str + ", 错误: " + parseEx.getMessage());
						continue;
					}
					
					if (dt1.compareTo(dt2) > 0)
					{
						continue;
					}
				//}

					//记录执行过的时间点，如果有该时间点，就不要在执行了。
					// 这里的时间点是有问题的，之前是根据当前时刻计算，其实是不对的。
					// 应该根据设定的时间保存时刻。
					String pkval = "";
					//是按照一天的时间点计算的.
					if (s.contains("LastDayOfMonth")) // 月度任务
					{
						pkval = "AutoFlow_" + fl.getNo() + "_" + dt1.format(DateTimeFormatter.ofPattern("yyyyMM")) + str;
					}
					else if (s.contains("Week.")) //按周计算.
					{
						pkval = "AutoFlow_" + fl.getNo() + "_" + dt1.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + dt.getDayOfWeek() + str;
					}
					else if (str.contains(":"))
					{
						pkval = "AutoFlow_" + fl.getNo() + "_" + dt1.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + str;
					}
					else
					{
						Log.DebugWriteError("不合法的发起规则: " + s);
					}


					GloVar gv = new GloVar();
					gv.setNo(pkval);
					if (gv.RetrieveFromDBSources() == 0)
					{
						gv.setName(fl.getName() + "自动发起.");
						gv.setGroupKey("AutoStartFlow");
						gv.Insert();
						Log.DebugWriteInfo("任务发起：" + gv.getName() +", No: " + gv.getNo());
						isHave = true; //可以执行.
						break;
					}
				}
				if (isHave == false)
				{
					continue;
				}
			}

				///#endregion 高级设置模式，是否达到启动的时间点？



			// 以此用户进入.
			switch (fl.getHisFlowRunWay())
			{
				case SpecEmp: //指定人员按时运行。
					msg += "<br>触发了:指定人员按时运行.";
					this.SpecEmp(fl);
					continue;
				case SelectSQLModel: //按数据集启动。
					this.SelectSQLModel(fl);
					continue;
				case WF_TaskTableInsertModel: //触发式启动。
					this.WF_TaskTableInsertModel(fl);
					continue;
				case SpecEmpAdv: //指定人员按时运行 高级模式.。
					msg += "<br>触发了:指定人员按时运行 高级模式.";
					msg += this.SpecEmpAdv(fl);
					continue;
                case LetAdminSendSpecEmp: //让admin发送给指定的人员.。
                    msg += "<br>触发了:让admin发送给指定的人员.";
                    msg += this.LetAdminSendSpecEmp(fl);
                    continue;
				default:
					break;
			}
		}
        if (!Objects.equals(WebUser.getNo(), "admin"))
        {
            // 直接使用接口登录 admin，避免对 Emp 实体的编译依赖
            Dev2Interface.Port_Login("admin");
        }

			///#endregion 发送消息

		return msg;
	}
	public final void SpecEmp(Flow fl) throws Exception {
		String RunObj = fl.getRunObj();
		String fk_emp = RunObj.substring(0, RunObj.indexOf('@'));

        try
        {
            //让 userNo 登录.
            Dev2Interface.Port_Login(fk_emp);

			//创建空白工作, 发起开始节点.
			long workID = Dev2Interface.Node_CreateBlankWork(fl.getNo());

			//执行发送.
			SendReturnObjs objs = Dev2Interface.Node_SendWork(fl.getNo(), workID);

			//String info_send= BP.WF.Dev2Interface.Node_StartWork(fl.No,);
			Log.DebugWriteInfo("流程:" + fl.getNo() + fl.getName() + "的定时任务\t\n -------------- \t\n" + objs.ToMsgOfText());
		}
		catch (RuntimeException ex)
		{
			Log.DebugWriteError("流程:" + fl.getNo() + fl.getName() + "自动发起错误:\t\n -------------- \t\n" + ex.getMessage());
		}
	}
	public final String LetAdminSendSpecEmp(Flow fl) throws Exception {
		String empsExp = fl.getStartGuidePara1(); //获得人员信息。
		if (DataType.IsNullOrEmpty(empsExp) == true)
		{
			return "配置的表达式错误:StartGuidePara1，人员信息不能为空。";
		}


			///#region 获得人员集合.
		String empsStr = ""; // 用于传递给 Node_SendWork 的人员字符串
		if (empsExp.toUpperCase().contains("SELECT") == true)
		{
			String strs = "";
			empsExp = Glo.DealExp(empsExp, null, null);
			DataTable dt = DBAccess.RunSQLReturnTable(empsExp);
			for (DataRow dr : dt.Rows)
			{
				strs += dr.getValue(0).toString() + ";";
			}
			empsStr = strs.length() > 0 && strs.endsWith(";") ? strs.substring(0, strs.length() - 1) : strs;
		}
		else
		{
			empsExp = empsExp.replace("@", ";");
			empsExp = empsExp.replace(",", ";");
			empsExp = empsExp.replace("、", ";");
			empsExp = empsExp.replace("，", ";");
			empsStr = empsExp;
		}

			///#endregion 获得人员集合.

		//让admin登录发送.
		Dev2Interface.Port_Login("admin");

		String msg = "";
		try
		{

			//创建空白工作, 发起开始节点.
			long workID = Dev2Interface.Node_CreateBlankWork(fl.getNo());

			// 修复：使用处理后的人员字符串 empsStr，而不是原始的 empsExp
			Dev2Interface.Node_SendWork(fl.getNo(), workID, 0, empsStr);

			String info = "流程:【" + fl.getNo() + fl.getName() + "】的定时任务 \t\n -------------- \t\n 已经启动，待办：" + empsStr + " , " + workID;
			Log.DebugWriteInfo(info);
			msg = info;
		}
		catch (RuntimeException ex)
		{
			String errMsg = "流程:" + fl.getNo() + fl.getName() + "自动发起错误:\t\n -------------- \t\n" + ex.getMessage();
			Log.DebugWriteError(errMsg);
			msg = errMsg;
		}
		return msg;
	}
	/** 
	 指定人员按时启动高级模式
	 
	 @param fl 流程
	 @return 
	*/
	public final String SpecEmpAdv(Flow fl) throws Exception {
		String empsExp = fl.getStartGuidePara1(); //获得人员信息。
		if (DataType.IsNullOrEmpty(empsExp) == true)
		{
			return "配置的表达式错误:StartGuidePara1，人员信息不能为空。";
		}


			///#region 获得人员集合.
		String[] emps = null;
		if (empsExp.toUpperCase().contains("SELECT") == true)
		{
			String strs = "";
			empsExp = Glo.DealExp(empsExp, null, null);
			DataTable dt = DBAccess.RunSQLReturnTable(empsExp);
			for (DataRow dr : dt.Rows)
			{
				strs += dr.getValue(0).toString() + ";";
			}
			emps = strs.split("[;]", -1);
			Log.DebugWriteInfo("strs:" + strs);
		}
		else
		{
			empsExp = empsExp.replace("@", ";");
			empsExp = empsExp.replace(",", ";");
			empsExp = empsExp.replace("、", ";");
			empsExp = empsExp.replace("，", ";");
			emps = empsExp.split("[;]", -1);
		}

			///#endregion 获得人员集合.

		String msg = "";
		int idx = 0;
		for (String emp : emps)
		{
			if (DataType.IsNullOrEmpty(emp) == true)
			{
				continue;
			}
			try
			{
				//让 emp 登录.
				Dev2Interface.Port_Login(emp);

				//创建空白工作, 发起开始节点.
				long workID = Dev2Interface.Node_CreateBlankWork(fl.getNo());

				//执行发送.
				SendReturnObjs objs = Dev2Interface.Node_SendWork(fl.getNo(), workID);

				String info = "流程:" + fl.getNo() + fl.getName() + "的定时任务\t\n -------------- \t\n 已经启动，待办：" + emp + " , " + workID;
				Log.DebugWriteInfo(info);
				idx++;
				msg += "<br/>第" + idx + "条:" + info;
			}
			catch (Exception ex)
			{
				Log.DebugWriteError("流程:" + fl.getNo() + fl.getName() + "自动发起错误:\t\n -------------- \t\n" + ex.getMessage());
			}
		}
		return msg;
	}
	/** 
	 触发模式
	 
	 @param fl
	*/
	public final void WF_TaskTableInsertModel(Flow fl) throws Exception {

		String info = "";
		String sql = "SELECT * FROM WF_Task WHERE TaskSta=0 AND FK_Flow='" + fl.getNo() + "' ORDER BY Starter";
		DataTable dt = null;
		try
		{
			dt = DBAccess.RunSQLReturnTable(sql);
		}
		catch (Exception e)
		{
			Task ta = new Task();
			ta.CheckPhysicsTable();
			dt = DBAccess.RunSQLReturnTable(sql);
		}
		MapData md = new MapData();
		switch (fl.getFlowDevModel()){
			case RefOneFrmTree://绑定单表单模式流程自动发起
				md = this.ExecuteRefOneFrmTree(fl);
				break;
			default: //其他模式默认专业模式流程自动发起，可自行扩展
				md = this.ExecuteProfessional(fl);
				break;
		}

		String whereStr = "";
		switch (md.getEntityType()){
			case FrmBill:
				whereStr = " BillState = 1";
				break;
			default:
				whereStr = " WFState = 1";
		}

		for (DataRow dr : dt.Rows)
		{
			String mypk = dr.getValue("MyPK").toString();
			String taskSta = dr.getValue("TaskSta").toString();
			String paras = dr.getValue("Paras").toString();
			String starter = dr.getValue("Starter").toString();
			String fk_flow = dr.getValue("FK_Flow").toString();

			//获得到达的节点，与接受人。
			String toEmps = dr.getValue("ToEmps").toString();
			if (DataType.IsNullOrEmpty(toEmps))
			{
				toEmps = null;
			}

			String toNodeStr = dr.getValue("ToNode").toString();
			int toNodeID = 0;
			if (!DataType.IsNullOrEmpty(toNodeStr))
			{
				toNodeID = Integer.parseInt(toNodeStr);
			}

			String startDT = dr.getValue("StartDT").toString();
			if (!StringHelper.isNullOrEmpty(startDT))
			{
				/*如果设置了发起时间,就检查当前时间是否与现在的时间匹配.*/
				DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
				String dateTimeString = LocalDateTime.now().format(formatter);
				LocalDateTime dateTime1 = LocalDateTime.parse(dateTimeString,formatter); //当前时间
				LocalDateTime dateTime2 = LocalDateTime.parse(startDT,formatter); // 设置发起时间
				if (dateTime1.isBefore(dateTime2))
				{
					continue;
				}
			}
			long workID = 0;
			try
			{
				String countSQL = "SELECT COUNT(MainPK) FROM " + md.getPTable() + " WHERE MainPK='" + mypk + "' ";
				if(!DataType.IsNullOrEmpty(whereStr)){
					countSQL += " AND " + whereStr;
				}
                int num = DBAccess.RunSQLReturnValInt(countSQL);
                if (num > 0)
                {
                    continue;
                }

                if (!Objects.equals(WebUser.getNo(), starter))
                {
                    WebUser.Exit();
                    Dev2Interface.Port_Login(starter);
                }

				//创建workid.
				workID = Dev2Interface.Node_CreateBlankWork(fk_flow);

				Node nd = new Node(Integer.parseInt(fk_flow + "01"));
				Work wk = nd.getHisWork();
				wk.setOID(workID);
				wk.RetrieveFromDBSources();

				String[] strs = paras.split("[@]", -1);
				for (String str : strs)
				{
					if (StringHelper.isNullOrEmpty(str))
					{
						continue;
					}

					if (!str.contains("="))
					{
						continue;
					}

					String[] kv = str.split("[=]", -1);
					if ("Title".equals(kv[0]))
					{
						throw new RuntimeException("err@温馨提示您不能使用Title字段，此字段是系统约定字段不可做为业务字段使用");
					}
					wk.SetValByKey(kv[0], kv[1]);
				}

				wk.SetValByKey("MainPK", mypk);
				wk.Update();

				WorkNode wn = new WorkNode(wk, fl.getHisStartNode());
				String msg = "";
				if (toNodeID == 0)
				{
					msg = wn.NodeSend(null, toEmps).ToMsgOfText();
				}
				else
				{
					msg = wn.NodeSend(new Node(toNodeID), toEmps).ToMsgOfText();
				}

				msg = msg.replace("'", "~");

				DBAccess.RunSQL("UPDATE WF_Task SET TaskSta=1,Msg='" + msg + "' WHERE MyPK='" + mypk + "'");
			}
			catch (RuntimeException ex)
			{
				//删除流程数据
				if (workID != 0)
				{
					Dev2Interface.Flow_DoDeleteFlowByReal(workID);
				}

				//如果发送错误。
				info += ex.getMessage();
				String msg = ex.getMessage();
				try
				{
					DBAccess.RunSQL("UPDATE WF_Task SET TaskSta=2,Msg='" + msg + "' WHERE MyPK='" + mypk + "'");
				}
				catch (Exception e)
				{
					Task TK = new Task();
					TK.CheckPhysicsTable();
				}
			}
		}
	}
	// 绑定单表单模式流程
	public final MapData ExecuteRefOneFrmTree(Flow fl) throws Exception {
		MapData md = new MapData(fl.getFrmUrl());
		md.RetrieveFromDBSources();
		return md;
	}
	// 专业模式流程
	public final MapData ExecuteProfessional(Flow fl) throws Exception {
		String fTable = "ND" + Integer.parseInt(fl.getNo() + "01");
		MapData md = new MapData(fTable);
		md.RetrieveFromDBSources();
		return md;
	}

	public final void SelectSQLModel(Flow fl) throws Exception {

			///#region 读取数据.
//		MapExt me = new MapExt();
//		me.setMyPK(MapExtXmlList.StartFlow + "_ND" + Integer.parseInt(fl.getNo()) + "01");
//		int i = me.RetrieveFromDBSources();
//		if (i == 0)
//		{
//			return;
//		}
		String tag = fl.getRunObj();
		tag = Glo.DealExp(tag, null); //处理sql表达式

		if (DataType.IsNullOrEmpty(tag))
		{
			Log.DebugWriteError("没有为流程(" + fl.getName() + ")的开始节点设置发起数据,请参考说明书解决.");
			return;
		}



			///#endregion 读取数据.


			///#region 检查数据源是否正确.
		String errMsg = "";
		// 获取主表数据.
		DataTable dtMain = DBAccess.RunSQLReturnTable(tag);
		if (dtMain.Rows.size() == 0)
		{
			Log.DebugWriteError("流程(" + fl.getName() + ")此时无任务.");
			return;
		}

		if (dtMain.Columns.contains("Starter") == false)
		{
			errMsg += "@配值的主表中没有Starter列.";
		}

		if (dtMain.Columns.contains("MainPK") == false)
		{
			errMsg += "@配值的主表中没有MainPK列.";
		}

		if (errMsg.length() > 2)
		{
			Log.DebugWriteError("流程(" + fl.getName() + ")的开始节点设置发起数据,不完整." + errMsg);

			return;
		}

			///#endregion 检查数据源是否正确.


			///#region 处理流程发起.
		String frmID = "ND" + Integer.parseInt(fl.getNo()) + "01";

		String err = "";
		int idx = 0;
		for (DataRow dr : dtMain.Rows)
		{
			idx++;

			String mainPK = dr.getValue("MainPK").toString();
			String sql = "SELECT OID FROM " + fl.getPTable() + " WHERE MainPK='" + mainPK + "'";
			if (DBAccess.RunSQLReturnTable(sql).Rows.size() != 0)
			{
				continue; //说明已经调度过了
			}

			String starter = dr.getValue("Starter").toString();
            if (!Objects.equals(WebUser.getNo(), starter))
            {
                WebUser.Exit();
                try {
                    Dev2Interface.Port_Login(starter);
                } catch (RuntimeException e) {
                    Log.DebugWriteInfo("@数据驱动方式发起流程(" + fl.getName() + ")设置的发起人员:" + starter + "不存在。");
                    continue;
                }
            }


				///#region  给值.
			//System.Collections.Hashtable ht = new Hashtable();
			//创建workid.
			long workID = Dev2Interface.Node_CreateBlankWork(fl.getNo(), null, null, starter, null);

			//创建工作.
			GEEntity wk = new GEEntity(frmID, workID);
			// Work wk = fl.NewWork();

			//给主表赋值.
			for (DataColumn dc : dtMain.Columns)
			{
				wk.SetValByKey(dc.ColumnName, dr.getValue(dc.ColumnName).toString());
			}

			// 获取从表数据.
			DataSet ds = new DataSet();
//			String[] dtlSQLs = me.getTag1().split("[*]", -1);
//			for (String sqlDtl : dtlSQLs)
//			{
//				if (DataType.IsNullOrEmpty(sqlDtl))
//				{
//					continue;
//				}
//
//				//替换变量.
//				String mySqlDtl = sqlDtl.replace("@MainPK", mainPK);
//
//				String[] tempStrs = mySqlDtl.split("[=]", -1);
//				String dtlName = tempStrs[0];
//				DataTable dtlTable = DBAccess.RunSQLReturnTable(mySqlDtl.replace(dtlName + "=", ""));
//				dtlTable.TableName = dtlName;
//				ds.Tables.add(dtlTable);
//			}

				///#endregion  给值.


				///#region 取出约定的到达人员.
			int toNodeID = 0;
			try
			{
				toNodeID = Integer.parseInt(dr.getValue("ToNode").toString());
			}
			catch (Exception e)
			{
				/*有可能在4.5以前的版本中没有tonode这个约定.*/
			}
			String toEmps = null;
			try
			{
				toEmps = dr.getValue("ToEmps").toString();
			}
			catch (Exception e2)
			{
				/*有可能在4.5以前的版本中没有tonode这个约定.*/
			}

				///#endregion 取出约定的到达人员.

			// 处理发送信息.
			//  Node nd =new Node();
			String msg = "";
			try
			{

				//执行发送到下一个节点.
				SendReturnObjs objs = Dev2Interface.Node_SendWork(fl.getNo(), workID, wk.getRow(), ds, toNodeID, toEmps);

				msg = "@自动发起:" + mainPK + "第" + idx + "条:  - " + objs.getMsgOfText();
				Log.DebugWriteInfo(msg);
			}
			catch (RuntimeException ex)
			{
				Log.DebugWriteError("@" + fl.getName() + ",第" + idx + "条,发起人员:" + WebUser.getNo() + "-" + WebUser.getName() + "发起时出现错误.\r\n" + ex.getMessage());
			}
		}

			///#endregion 处理流程发起.
	}
}
